"""
@File    : __init__.py.py
@Time    : 2025/7/15 下午5:31
@Author  : xiashuobad
@Desc    : 

/**
 * _ooOoo_
 * o8888888o
 * 88" . "88
 * (| -_- |)
 *  O\ = /O
 * ___/`---'\____
 * .   ' \\| |// `.
 * / \\||| : |||// \
 * / _||||| -:- |||||- \
 * | | \\\ - /// | |
 * | \_| ''\---/'' | |
 * \ .-\__ `-` ___/-. /
 * ___`. .' /--.--\ `. . __
 * ."" '< `.___\_<|>_/___.' >'"".
 * | | : `- \`.;`\ _ /`;.`/ - ` : | |
 * \ \ `-. \_ __\ /__ _/ .-` / /
 * ======`-.____`-.___\_____/___.-`____.-'======
 * `=---=' bug泛滥 佛已瘫痪
"""

# rsio/core/backends/image_backend.py
import numpy as np
from abc import ABC, abstractmethod
from pathlib import Path
from functools import wraps
from typing import Type

from ..utils import type_check, ArrayShapeConverter, ImageModeError


class ImageBackend(ABC):
    """
    图像 IO 后端抽象基类
    """
    registered_backends = {}

    def __init__(self, file_path: str, mode: str, **kwargs):
        self._fp = Path(file_path)
        self._mode = self._checked_mode(mode)
        self._kwargs = kwargs
        self._img_array = None
        self._open()

    @classmethod
    def __init_subclass__(cls, **kwargs):
        ImageBackend.registered_backends[kwargs['backend_name']] = cls

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()

    @abstractmethod
    def _open(self):
        ...

    @property
    def file_path(self) -> str:
        return str(self._fp)

    @property
    def mode(self) -> str:
        return self._mode

    @property
    def kwargs(self) -> dict:
        return self._kwargs

    @property
    def file_name(self) -> str:
        return self._fp.stem

    @property
    def img_suffix(self) -> str:
        return self._fp.suffix.lower()

    @property
    def img_array(self) -> np.ndarray:
        return self._img_array

    @img_array.setter
    @abstractmethod
    def img_array(self, img_array: np.ndarray):
        ...

    @abstractmethod
    def save(self, **meta):
        ...

    @property
    @abstractmethod
    def shape(self) -> tuple[int, int] | tuple[int, int, int]:
        ...

    @property
    @abstractmethod
    def size(self) -> tuple[int, int]:
        ...

    @property
    @abstractmethod
    def channel(self) -> int:
        ...

    @property
    @abstractmethod
    def width(self) -> int:
        ...

    @property
    @abstractmethod
    def height(self) -> int:
        ...

    @property
    @abstractmethod
    def dtype(self) -> np.dtype | str | Type[np.number]:
        ...

    @abstractmethod
    def resize(self, target_size: tuple[int, int], **kwargs):
        ...

    @abstractmethod
    def reverse_rgb(self):
        ...

    @abstractmethod
    def crop(self, x_off: int = 0, y_off: int = 0, window_x_size: int = None, window_y_size: int = None):
        ...

    def close(self):
        self._img_array = None

    def _checked_mode(self, mode: str) -> str:
        return mode

    @staticmethod
    def require_write_mode(method):
        @wraps(method)
        def wrapper(instance, *args, **kwargs):
            if instance.mode == 'r':
                raise ImageModeError(f'当前为只读模式，无法保存修改！')
            return method(instance, *args, **kwargs)

        return wrapper

    @staticmethod
    @type_check
    def array_channels(array: np.ndarray) -> int:
        array = ArrayShapeConverter.array_shape_to_gdal(array)
        return 1 if len(array.shape) == 2 else array.shape[0]
